package com.zhijian.warehouse.manage.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.zhijian.warehouse.manage.dao.RoleMapper;
import com.zhijian.warehouse.manage.entity.po.Role;
import com.zhijian.warehouse.manage.entity.po.RoleMenu;
import com.zhijian.warehouse.manage.entity.vo.request.RoleSaveOrUpdateVo;
import com.zhijian.warehouse.manage.entity.vo.request.RoleSearchVo;
import com.zhijian.warehouse.manage.entity.vo.request.UserRoleSearchVo;
import com.zhijian.warehouse.manage.entity.vo.response.RoleVo;
import com.zhijian.warehouse.manage.entity.vo.response.UserRoleVo;
import com.zhijian.warehouse.manage.enums.ResponseEnum;
import com.zhijian.warehouse.manage.service.RoleMenuService;
import com.zhijian.warehouse.manage.service.RoleService;
import com.zhijian.warehouse.manage.service.UserRoleService;
import com.zhijian.warehouse.manage.util.AssertCommonUtil;
import com.zhijian.util.page.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 系统角色信息业务处理层
 *
 * @author HCG
 * @version: 1.0
 * @date 2022-01-22 15:37:30
 */
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper mapper;

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private UserRoleService userRoleService;

    @Override
    public Role selectById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public RoleVo selectVoById(Long id) {
        RoleVo roleVo = mapper.selectVoById(id);
        if (Objects.nonNull(roleVo)) {
            roleVo.setMenuIds(roleMenuService.selectMenuIdsByRoleId(id));
        }
        return roleVo;
    }

    @Override
    public RoleVo selectByUserId(Long userId) {
        return mapper.selectByUserId(userId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteById(Long id) {
        Role role = this.selectById(id);
        AssertCommonUtil.notNull(role, ResponseEnum.DATA_NULL);
        List<UserRoleVo> userRoleList = userRoleService.selectList(UserRoleSearchVo.builder()
                .roleId(id)
                .build());
        AssertCommonUtil.check(CollectionUtil.isNotEmpty(userRoleList), ResponseEnum.DELETE_DEPENDENT_DATA_FIRST);
        mapper.deleteByPrimaryKey(id);
        roleMenuService.deleteByRoleId(id);
    }

    @Override
    public Long insert(Role role) {
        Date now = new Date();
        role.setCreateTime(now);
        role.setUpdateTime(now);
        return mapper.insert(role) > 0 ? role.getId() : 0L;
    }

    @Override
    public boolean update(Role role) {
        Role oldRole = this.selectById(role.getId());
        AssertCommonUtil.notNull(oldRole, ResponseEnum.DATA_NULL);
        Date now = new Date();
        role.setUpdateTime(now);
        role.setTenantId(oldRole.getTenantId());
        return mapper.updateByPrimaryKey(role) != 0;
    }

    @Override
    public boolean updateByPrimaryKeySelective(Role record) {
        Date now = new Date();
        record.setUpdateTime(now);
        return mapper.updateByPrimaryKeySelective(record) != 0;
    }

    @Override
    public Integer count(RoleSearchVo roleSearchVo) {
        return mapper.count(roleSearchVo);
    }

    @Override
    public List<RoleVo> selectList(RoleSearchVo roleSearchVo) {
        List<RoleVo> roleVos = mapper.selectList(roleSearchVo);
        if (CollectionUtil.isEmpty(roleVos)) {
            return Collections.emptyList();
        }
        roleVos.forEach(roleVo -> {
            //赋值菜单名
            roleVo.setMenuNames(roleMenuService.selectMenuNamesByRoleId(roleVo.getId()));
            roleVo.setMenuIds(roleMenuService.selectMenuIdsByRoleId(roleVo.getId()));
        });
        return roleVos;
    }

    @Override
    public Page<RoleVo> selectPage(RoleSearchVo roleSearchVo) {
        //先直接查总数
        int count = count(roleSearchVo);
        //分页
        Page<RoleVo> page = new Page<>(true, count, roleSearchVo.getPageNum(), roleSearchVo.getPageSize());
        roleSearchVo.setStartIndex(page.getStartIndex());
        page.setPage(true);
        page.setTotalCount(count);
        List<RoleVo> responseVos = this.selectList(roleSearchVo);
        page.setData(responseVos);
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean connectMenus(Long roleId, List<Long> menuIds) {
        //先把之前的全部删掉
        roleMenuService.deleteByRoleId(roleId);
        Date now = new Date();
        List<RoleMenu> roleMenus = menuIds.stream().map(menuId -> RoleMenu.builder()
                .menuId(menuId)
                .roleId(roleId)
                .createTime(now)
                .updateTime(now)
                .build()).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(roleMenus)) {
            roleMenuService.insertBatch(roleMenus);
        }
        return true;
    }

    @Override
    public RoleVo selectVoByName(String name) {
        return mapper.selectVoByName(name);
    }

    @Override
    public RoleVo selectVoByCode(String code) {
        return mapper.selectVoByCode(code);
    }

    @Override
    public void deleteByIdList(List<Long> idList) {
        if (CollectionUtil.isEmpty(idList)) {
            return;
        }
        for (Long id : idList) {
            List<UserRoleVo> userRoleList = userRoleService.selectList(UserRoleSearchVo.builder()
                    .roleId(id)
                    .build());
            AssertCommonUtil.check(CollectionUtil.isNotEmpty(userRoleList), ResponseEnum.DELETE_DEPENDENT_DATA_FIRST);
        }
        mapper.deleteByIdList(idList);
    }

    @Override
    public boolean insertBatch(List<Role> entities) {
        return CollectionUtil.isNotEmpty(entities) && mapper.insertBatch(entities) > 0;
    }

    @Override
    public boolean save(RoleSaveOrUpdateVo roleSaveOrUpdateVo) {
        Role role = new Role();
        BeanUtils.copyProperties(roleSaveOrUpdateVo, role);
        return this.insert(role) != 0;
    }

    @Override
    public boolean modify(RoleSaveOrUpdateVo roleSaveOrUpdateVo) {
        Role role = new Role();
        BeanUtils.copyProperties(roleSaveOrUpdateVo, role);
        this.update(role);
        return true;
    }
}